﻿Imports UCBase
Imports DirectShowLib
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.Drawing.Imaging
Imports System.Windows.Forms
Imports System.Drawing
Public Class AdvanceCam2
    Inherits UserControl
    Implements ISampleGrabberCB

    Private capDevices As DsDevice()
    Private m_FilterGraph As IFilterGraph2 = Nothing
    Private m_VidControl As IAMVideoControl = Nothing
    Private m_pinStill As IPin = Nothing
    Private m_rot As DsROTEntry = Nothing
    Private m_ip As IntPtr = IntPtr.Zero
    Private m_CamControl As IAMCameraControl = Nothing
    Private m_VideoProcAmp As IAMVideoProcAmp = Nothing
    Private M_Capture As IAMStreamConfig = Nothing
    Private m_PictureReady As ManualResetEvent = Nothing
    Private m_WantOne As Boolean = False
    Private m_videoWidth As Integer
    Private m_videoHeight As Integer
    Private m_stride As Integer
    Private m_bits As Integer
    Private m_ipBuffer As IntPtr = IntPtr.Zero
    Private M_ResolutionModes As New Collection
    Private SelectedDevice As Integer
    Private SelectedPreviewMode As Integer
    Private SelectedCaptureMode As Integer
    'Public Event ImageReady(ByVal Image As Bitmap)
    Private M_RUN As Boolean = False
    Private CanPreview As Boolean = False
    Private InternalPreview As Boolean = True
    Private HaveVidWin As Boolean = False
    Private M_Edit As Boolean = True

    Private M_ImageEnabled As Boolean = False
    Private M_ImageConnected As Boolean = False
    Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox
    Friend WithEvents ComboBox2 As System.Windows.Forms.ComboBox
    Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
    Friend WithEvents Label2 As System.Windows.Forms.Label
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    Friend WithEvents Led1 As UCBase.Led
    Friend WithEvents Led2 As UCBase.Led
    Private M_auto_Trigger As Boolean = False

    Private Sub InitializeComponent()
        Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(AdvanceCam2))
        Me.ComboBox1 = New System.Windows.Forms.ComboBox
        Me.ComboBox2 = New System.Windows.Forms.ComboBox
        Me.CheckBox1 = New System.Windows.Forms.CheckBox
        Me.Label2 = New System.Windows.Forms.Label
        Me.Label1 = New System.Windows.Forms.Label
        Me.PictureBox1 = New System.Windows.Forms.PictureBox
        Me.Led1 = New UCBase.Led
        Me.Led2 = New UCBase.Led
        CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'ComboBox1
        '
        Me.ComboBox1.FormattingEnabled = True
        Me.ComboBox1.Location = New System.Drawing.Point(350, 25)
        Me.ComboBox1.Name = "ComboBox1"
        Me.ComboBox1.Size = New System.Drawing.Size(175, 21)
        Me.ComboBox1.TabIndex = 42
        '
        'ComboBox2
        '
        Me.ComboBox2.Enabled = False
        Me.ComboBox2.FormattingEnabled = True
        Me.ComboBox2.Location = New System.Drawing.Point(350, 70)
        Me.ComboBox2.Name = "ComboBox2"
        Me.ComboBox2.Size = New System.Drawing.Size(175, 21)
        Me.ComboBox2.TabIndex = 43
        '
        'CheckBox1
        '
        Me.CheckBox1.AutoSize = True
        Me.CheckBox1.Location = New System.Drawing.Point(350, 100)
        Me.CheckBox1.Name = "CheckBox1"
        Me.CheckBox1.Size = New System.Drawing.Size(125, 17)
        Me.CheckBox1.TabIndex = 46
        Me.CheckBox1.Text = "Use Still/Preview Pin"
        Me.CheckBox1.UseVisualStyleBackColor = True
        '
        'Label2
        '
        Me.Label2.AutoSize = True
        Me.Label2.BackColor = System.Drawing.Color.Transparent
        Me.Label2.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.Label2.Location = New System.Drawing.Point(350, 55)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(67, 13)
        Me.Label2.TabIndex = 45
        Me.Label2.Text = "Resolution"
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.BackColor = System.Drawing.Color.Transparent
        Me.Label1.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.Label1.Location = New System.Drawing.Point(350, 10)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(47, 13)
        Me.Label1.TabIndex = 44
        Me.Label1.Text = "Device"
        '
        'PictureBox1
        '
        Me.PictureBox1.BackColor = System.Drawing.Color.Black
        Me.PictureBox1.Location = New System.Drawing.Point(10, 10)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(335, 250)
        Me.PictureBox1.TabIndex = 47
        Me.PictureBox1.TabStop = False
        '
        'Led1
        '
        Me.Led1.BackColor = System.Drawing.Color.Transparent
        Me.Led1.LedSize = 2
        Me.Led1.Location = New System.Drawing.Point(390, 180)
        Me.Led1.Name = "Led1"
        Me.Led1.Off_Color = System.Drawing.Color.DarkBlue
        Me.Led1.On_Color = System.Drawing.Color.SkyBlue
        Me.Led1.Size = New System.Drawing.Size(20, 20)
        Me.Led1.State = UCBase.Led.LedState.Led_Off
        Me.Led1.TabIndex = 48
        Me.Led1.X_Offset = 1
        Me.Led1.Y_Offset = 1
        '
        'Led2
        '
        Me.Led2.BackColor = System.Drawing.Color.Transparent
        Me.Led2.LedSize = 2
        Me.Led2.Location = New System.Drawing.Point(390, 205)
        Me.Led2.Name = "Led2"
        Me.Led2.Off_Color = System.Drawing.Color.DarkBlue
        Me.Led2.On_Color = System.Drawing.Color.SkyBlue
        Me.Led2.Size = New System.Drawing.Size(20, 20)
        Me.Led2.State = UCBase.Led.LedState.Led_Off
        Me.Led2.TabIndex = 49
        Me.Led2.X_Offset = 1
        Me.Led2.Y_Offset = 1
        '
        'AdvanceCam
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.BackgroundImage = CType(resources.GetObject("$this.BackgroundImage"), System.Drawing.Image)
        Me.Controls.Add(Me.Led2)
        Me.Controls.Add(Me.Led1)
        Me.Controls.Add(Me.PictureBox1)
        Me.Controls.Add(Me.ComboBox1)
        Me.Controls.Add(Me.ComboBox2)
        Me.Controls.Add(Me.CheckBox1)
        Me.Controls.Add(Me.Label2)
        Me.Controls.Add(Me.Label1)
        Me.Name = "AdvanceCam"
        Me.Size = New System.Drawing.Size(651, 382)
        CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub

    Public Function BufferCB(ByVal SampleTime As Double, ByVal pBuffer As System.IntPtr, ByVal BufferLen As Integer) As Integer Implements DirectShowLib.ISampleGrabberCB.BufferCB

    End Function

    Public Function SampleCB(ByVal SampleTime As Double, ByVal pSample As DirectShowLib.IMediaSample) As Integer Implements DirectShowLib.ISampleGrabberCB.SampleCB

    End Function
    Private Sub SetupGraph()
        Dim hr As Integer

        Dim sampGrabber As ISampleGrabber = Nothing
        Dim capFilter As IBaseFilter = Nothing
        Dim pCaptureOut As IPin = Nothing
        Dim pSampleIn As IPin = Nothing
        Dim pRenderIn As IPin = Nothing
        Dim dev As DsDevice = capDevices(SelectedDevice)
        m_FilterGraph = TryCast(New FilterGraph(), IFilterGraph2)

        Try
            m_rot = New DsROTEntry(m_FilterGraph)

            ' add the video input device
            hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, Nothing, dev.Name, capFilter)
            DsError.ThrowExceptionForHR(hr)

            ' Set up controls
            m_CamControl = TryCast(capFilter, IAMCameraControl)

            m_VideoProcAmp = TryCast(capFilter, IAMVideoProcAmp)

            If CheckBox1.Checked Then
                ' Find the still pin
                m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0)

                ' Didn't find one.  Is there a preview pin?
                If m_pinStill Is Nothing Then
                    m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0)
                End If
            End If

            ' Still haven't found one.  Need to put a splitter in so we have
            ' one stream to capture the bitmap from, and one to display.  Ok, we
            ' don't *have* to do it that way, but we are going to anyway.
            If m_pinStill Is Nothing Then
                Dim pRaw As IPin = Nothing
                Dim pSmart As IPin = Nothing

                ' There is no still pin
                m_VidControl = Nothing

                ' Add a splitter
                Dim iSmartTee As IBaseFilter = DirectCast(New SmartTee(), IBaseFilter)

                Try
                    hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee")
                    DsError.ThrowExceptionForHR(hr)

                    ' Find the find the capture pin from the video device and the
                    ' input pin for the splitter, and connnect them
                    pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0)
                    pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0)

                    hr = m_FilterGraph.Connect(pRaw, pSmart)
                    DsError.ThrowExceptionForHR(hr)

                    ' Now set the capture and still pins (from the splitter)
                    m_pinStill = DsFindPin.ByName(iSmartTee, "Preview")
                    pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture")

                    ' If any of the default config items are set, perform the config
                    ' on the actual video device (rather than the splitter)
                    'If iHeight + iWidth + iBPP > 0 Then
                    SetConfigParms(pRaw)
                    'End If
                Finally
                    If pRaw IsNot Nothing Then
                        Marshal.ReleaseComObject(pRaw)
                    End If
                    If pRaw IsNot pSmart Then
                        Marshal.ReleaseComObject(pSmart)
                    End If
                    If pRaw IsNot iSmartTee Then
                        Marshal.ReleaseComObject(iSmartTee)
                    End If
                End Try
            Else
                ' Get a control pointer (used in Click())
                m_VidControl = TryCast(capFilter, IAMVideoControl)
                pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0)

                M_Capture = TryCast(pCaptureOut, IAMStreamConfig)

                ' If any of the default config items are set

                'If iHeight + iWidth + iBPP > 0 Then
                SetConfigParms(m_pinStill)
                'End If
            End If

            ' Get the SampleGrabber interface
            sampGrabber = TryCast(New SampleGrabber(), ISampleGrabber)

            ' Configure the sample grabber
            Dim baseGrabFlt As IBaseFilter = TryCast(sampGrabber, IBaseFilter)
            ConfigureSampleGrabber(sampGrabber)
            pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0)

            ' Get the default video renderer
            Dim pRenderer As IBaseFilter = TryCast(New VideoRendererDefault(), IBaseFilter)
            hr = m_FilterGraph.AddFilter(pRenderer, "Renderer")
            DsError.ThrowExceptionForHR(hr)

            pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0)

            ' Add the sample grabber to the graph
            hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber")
            DsError.ThrowExceptionForHR(hr)

            If m_VidControl Is Nothing Then
                ' Connect the Still pin to the sample grabber
                hr = m_FilterGraph.Connect(m_pinStill, pSampleIn)
                DsError.ThrowExceptionForHR(hr)

                ' Connect the capture pin to the renderer
                hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn)
                DsError.ThrowExceptionForHR(hr)
            Else
                ' Connect the capture pin to the renderer
                hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn)
                DsError.ThrowExceptionForHR(hr)

                ' Connect the Still pin to the sample grabber
                hr = m_FilterGraph.Connect(m_pinStill, pSampleIn)
                DsError.ThrowExceptionForHR(hr)
            End If

            ' Learn the video properties
            SaveSizeInfo(sampGrabber)
            ConfigVideoWindow(PictureBox1)
            ' Start the graph
            Dim mediaCtrl As IMediaControl = TryCast(m_FilterGraph, IMediaControl)
            hr = mediaCtrl.Run()
            DsError.ThrowExceptionForHR(hr)
        Finally
            If sampGrabber IsNot Nothing Then
                Marshal.ReleaseComObject(sampGrabber)
                sampGrabber = Nothing
            End If
            If pCaptureOut IsNot Nothing Then
                Marshal.ReleaseComObject(pCaptureOut)
                pCaptureOut = Nothing
            End If
            If pRenderIn IsNot Nothing Then
                Marshal.ReleaseComObject(pRenderIn)
                pRenderIn = Nothing
            End If
            If pSampleIn IsNot Nothing Then
                Marshal.ReleaseComObject(pSampleIn)
                pSampleIn = Nothing
            End If
        End Try
        M_RUN = True
    End Sub
    Private Sub ConfigureSampleGrabber(ByVal sampGrabber As ISampleGrabber)
        Dim hr As Integer
        Dim media As New AMMediaType()

        ' Set the media type to Video/RBG24
        media.majorType = MediaType.Video
        media.subType = MediaSubType.RGB24
        media.formatType = FormatType.VideoInfo
        hr = sampGrabber.SetMediaType(media)
        DsError.ThrowExceptionForHR(hr)

        DsUtils.FreeAMMediaType(media)
        media = Nothing

        ' Configure the samplegrabber
        hr = sampGrabber.SetCallback(Me, 1)
        DsError.ThrowExceptionForHR(hr)
    End Sub
    Private Sub SaveSizeInfo(ByVal sampGrabber As ISampleGrabber)
        Dim hr As Integer

        ' Get the media type from the SampleGrabber
        Dim media As New AMMediaType()

        hr = sampGrabber.GetConnectedMediaType(media)
        DsError.ThrowExceptionForHR(hr)

        If (media.formatType <> FormatType.VideoInfo) OrElse (media.formatPtr = IntPtr.Zero) Then
            Throw New NotSupportedException("Unknown Grabber Media Format")
        End If

        ' Grab the size info
        Dim videoInfoHeader As VideoInfoHeader = DirectCast(Marshal.PtrToStructure(media.formatPtr, GetType(VideoInfoHeader)), VideoInfoHeader)
        m_videoWidth = videoInfoHeader.BmiHeader.Width
        m_videoHeight = videoInfoHeader.BmiHeader.Height
        m_stride = m_videoWidth * (videoInfoHeader.BmiHeader.BitCount / 8)
        m_bits = videoInfoHeader.BmiHeader.BitCount
        DsUtils.FreeAMMediaType(media)
        media = Nothing
    End Sub

    Private Sub ConfigVideoWindow(ByVal hControl As Control)
        Dim hr As Integer
        If InternalPreview = True Then hControl = PictureBox1
        Dim ivw As IVideoWindow = TryCast(m_FilterGraph, IVideoWindow)

        ' Set the parent
        hr = ivw.put_Owner(hControl.Handle)
        DsError.ThrowExceptionForHR(hr)

        ' Turn off captions, etc
        hr = ivw.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipChildren Or WindowStyle.ClipSiblings)
        DsError.ThrowExceptionForHR(hr)

        ' Yes, make it visible
        If InternalPreview = False Then
            hr = ivw.put_Visible(OABool.True)
            DsError.ThrowExceptionForHR(hr)
            If HaveVidWin = True Then Led1.State = Led.LedState.Led_On
        Else
            hr = ivw.put_Visible(OABool.False)
            DsError.ThrowExceptionForHR(hr)
        End If
        ' Move to upper left corner
        Dim rc As Rectangle = hControl.ClientRectangle
        Dim r As Double = m_videoWidth / m_videoHeight
        Dim w As Integer = hControl.Height * r
        Dim L As Integer = (hControl.Width / 2) - (w / 2)
        hr = ivw.SetWindowPosition(L, 0, w, hControl.Height)

        DsError.ThrowExceptionForHR(hr)
    End Sub
    ' Set the Framerate, and video size
    Private Sub SetConfigParms(ByVal pStill As IPin)
        Dim hr As Integer
        Dim streamConfig As IAMStreamConfig = DirectCast(pStill, IAMStreamConfig)
        Dim searchmedia As AMMediaType = Nothing
        Dim CorectvidFormat As New AMMediaType()
        Dim ptr As IntPtr

        Dim piCount As Integer, piSize As Integer
        hr = streamConfig.GetNumberOfCapabilities(piCount, piSize)
        ptr = Marshal.AllocCoTaskMem(piSize)
        For i As Integer = 0 To piCount - 1
            hr = streamConfig.GetStreamCaps(i, searchmedia, ptr)
            Dim v As New VideoInfoHeader()
            Marshal.PtrToStructure(searchmedia.formatPtr, v)
            If i = SelectedPreviewMode Then
                CorectvidFormat = searchmedia
            End If
        Next
        hr = streamConfig.SetFormat(CorectvidFormat)
    End Sub
    Private Sub CloseInterfaces()
        Dim hr As Integer

        Try
            If m_FilterGraph IsNot Nothing Then
                Dim mediaCtrl As IMediaControl = TryCast(m_FilterGraph, IMediaControl)

                ' Stop the graph
                hr = mediaCtrl.[Stop]()
            End If
        Catch ex As Exception
            Debug.WriteLine(ex)
        End Try

        If m_FilterGraph IsNot Nothing Then
            Marshal.ReleaseComObject(m_FilterGraph)
            m_FilterGraph = Nothing
        End If

        If m_VidControl IsNot Nothing Then
            Marshal.ReleaseComObject(m_VidControl)
            m_VidControl = Nothing
        End If

        If m_pinStill IsNot Nothing Then
            Marshal.ReleaseComObject(m_pinStill)
            m_pinStill = Nothing
        End If
    End Sub
    Private Sub GetResolutions()
        Dim hr As Integer
        Dim dev As DsDevice = capDevices(SelectedDevice)
        Dim capFilter As IBaseFilter = Nothing
        m_FilterGraph = TryCast(New FilterGraph(), IFilterGraph2)

        Try
            hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, Nothing, dev.Name, capFilter)
            DsError.ThrowExceptionForHR(hr)
            m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0)
            If m_pinStill Is Nothing Then
                m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0)
            End If
            If m_pinStill Is Nothing Then
                m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0)
            End If

            Dim streamConfig As IAMStreamConfig = DirectCast(m_pinStill, IAMStreamConfig)
            Dim searchmedia As AMMediaType = Nothing
            Dim ptr As IntPtr

            Dim piCount As Integer, piSize As Integer
            hr = streamConfig.GetNumberOfCapabilities(piCount, piSize)
            ptr = Marshal.AllocCoTaskMem(piSize)
            For i As Integer = 0 To piCount - 1
                hr = streamConfig.GetStreamCaps(i, searchmedia, ptr)
                Dim vinfo As New VideoInfoHeader()
                Marshal.PtrToStructure(searchmedia.formatPtr, vinfo)
                If vinfo.BmiHeader.Width > 0 Then
                    ComboBox2.Items.Add("[" & i & "] = " & vinfo.BmiHeader.Width & " X " & vinfo.BmiHeader.Height & "(" & vinfo.BmiHeader.BitCount & ")" & " FPS:" & CInt(10000000 / vinfo.AvgTimePerFrame))
                    ComboBox2.Enabled = True
                End If
            Next

        Catch
        End Try

        If m_FilterGraph IsNot Nothing Then
            Marshal.ReleaseComObject(m_FilterGraph)
            m_FilterGraph = Nothing
        End If

        If m_pinStill IsNot Nothing Then
            Marshal.ReleaseComObject(m_pinStill)
            m_pinStill = Nothing
        End If
    End Sub
    Private Sub ComboBox2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox2.SelectedIndexChanged
        M_RUN = False
        Dim str As String = ComboBox2.SelectedItem
        Dim a As Integer = str.IndexOf("[") + 1
        Dim b As Integer = str.IndexOf("]")
        Dim l As Integer = b - a
        Dim n As String = str.Substring(a, l)
        SelectedPreviewMode = CInt(Val(n))
        CanPreview = True
        Led2.State = Led.LedState.Led_On
        CloseInterfaces()
        SetupGraph()
    End Sub
    Private Sub Cam_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
        'Dim C As Integer = 0
        'For Each Dev As DsDevice In capDevices
        ' ComboBox1.Items.Add("[" & C & "] " & Dev.Name)
        'C = C + 1
        'Next
        'm_PictureReady = New ManualResetEvent(False)
    End Sub
    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        SelectedDevice = ComboBox1.SelectedIndex
        GetResolutions()
    End Sub
End Class
